Skip to content

backlog: elevate git-native PR-preservation P2→P1 + phased plan (Otto-150..154)#335

Merged
AceHack merged 6 commits intomainfrom
backlog/otto-150-154-pr-preservation-phased-priority
Apr 24, 2026
Merged

backlog: elevate git-native PR-preservation P2→P1 + phased plan (Otto-150..154)#335
AceHack merged 6 commits intomainfrom
backlog/otto-150-154-pr-preservation-phased-priority

Conversation

@AceHack
Copy link
Copy Markdown
Member

@AceHack AceHack commented Apr 24, 2026

Summary

Aaron Otto-150..154 signal burst elevated git-native PR-conversation preservation priority (P2 → P1) and requested backfill. Course correction Otto-154 clarified: "no not that quick / do it the right way / i just mean pritorize the right way" — the ask is appropriate prioritization, not rushed shipping.

Expands the existing BACKLOG row (line 4280) into a 5-phase landing plan: design → privacy review (Aminata blocking) → ongoing capture (GHA workflow) → backfill (300+ PRs batched) → reconciliation hygiene.

Honest status

Currently NOT running. No workflow archives review threads. No docs/pr-discussions/ directory. Prior session summary implied this was ongoing; it was not. BACKLOG elevation makes this visible.

Also captured

Otto-154 operational-pattern learning: GHA workflows that reference github.event.pull_request.title / .body trigger the injection-reminder hook even when using the safe env: + quoted-shell pattern. Future implementers should fetch via gh api INSIDE the workflow instead — documented in Phase-3 body.

Test plan

  • BACKLOG row is the only change; git diff --stat shows 1 file, +67/-1.
  • Aminata threat-review pass (Phase 2) before any workflow lands.

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings April 24, 2026 08:33
@AceHack AceHack enabled auto-merge (squash) April 24, 2026 08:33
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Elevates and expands the BACKLOG item for preserving GitHub PR review conversations into git-tracked archives, clarifying that the capability is not currently running and laying out a phased plan to implement and backfill it.

Changes:

  • Promotes “git-native PR-conversation preservation” priority from P2 → P1 and corrects status to “NOT running”.
  • Replaces the single-row description with a 5-phase implementation plan (design → privacy review → workflow capture → backfill → reconciliation hygiene).
  • Documents an operational note about avoiding direct use of github.event.pull_request.title/body in workflows (per Otto-154).

Comment thread docs/BACKLOG.md Outdated
Comment thread docs/BACKLOG.md Outdated
Comment thread docs/BACKLOG.md Outdated
Comment thread docs/BACKLOG.md Outdated
AceHack added a commit that referenced this pull request Apr 24, 2026
…on (#356)

Maintainer Otto-204: "you need some pr resolve loop that will
handled everyting needed to take a pr to compelteion so you
don't ahve to keep figuion it out" + Otto-204b: "we are
saving you resolution to all the comments and we expect
those to be excellent don't take shortcuts on the feedback,
do the right long term thing or backlog the right thing and
not it on the comment."

New P1 CI/DX BACKLOG row for .claude/skills/pr-resolve-loop/
SKILL.md. Six-step close cycle: CI-status → review-thread
resolution (reply-then-resolve; never shortcut) → name-
attribution lint → conversation-preservation hook → auto-
merge re-arm → loop-exit on merge / maintainer-escalation /
external-blocker.

Core discipline: active PR management vs ship-and-pray. The
factory's Otto-200..203 observation of "queue unchanged 136"
for 6+ ticks misread passive-stuck as livelock; actual
blocker was accumulated unresolved review-threads + silent
lint failures that armed auto-merge could not overcome. This
skill internalizes that learning; active resolution has
10-20× higher ROI than opening new PRs when queue saturated.

Conversation-preservation: every reply+resolve logs to
artifacts/pr-discussions/PR-<N>-conversation-log.json per
Otto-150..154 git-native preservation directive.

Non-goals: NOT an auto-merge-bypass, NOT a shortcut around
reviewer intent, NOT a retry-loop on flake, NOT an opener of
new PRs.

Composes with: Otto-171 queue-saturation-throttle, PR #335
preservation, @codex review + Copilot patterns, PR #213
git-hotspots, PR #354 BACKLOG-split-Phase-1a (first PR where
active-management discipline applied).

Priority P1 CI/DX. Effort: M skill design + S invocation +
S reply-template bank.

Placed in P1 CI/DX section line 2469, NOT BACKLOG tail.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
AceHack added a commit that referenced this pull request Apr 24, 2026
…security + privacy-posture correction

Active PR-resolve-loop on #335 PR-preservation elevation row.

1. GHA workflow trigger syntax (thread 59Vtx0): replaced
   the incorrect-looking "pull_request_target: closed with
   merged == true" prose with a proper YAML fence showing
   the actual trigger shape (on: pull_request_target →
   types: [closed]) + the job-level if: github.event.
   pull_request.merged == true gate. Now reads as
   implementation hint instead of literal-but-wrong YAML.

2. pull_request_target security constraints (thread
   59VtyM): added an explicit MUST/SHOULD list constraining
   the Phase 3 workflow away from the known pull_request_
   target footgun (elevated permissions + fork-authored
   PR-head code execution). Constraints: no checkout of
   PR head; no ${{ github.event.pull_request.* }} in
   run: steps; minimal permissions declaration; SHA-
   pinned actions. Fetches title/metadata via gh api
   inside the workflow, never from event payload.

3. docs-lint / memory-no-lint policy citation (thread
   59VtxI): replaced vague "docs-lint/memory-no-lint
   policy" phrase with concrete cross-reference to
   memory/feedback_docs_linted_memory_not_otto_decides_*
   (policy) + .markdownlint-cli2.jsonc (enforcement via
   memory/** ignore patterns).

4. Privacy-posture on agent content (thread 59Vtyl):
   walked back the unsafe "agent content without privacy
   concern" non-goal. New framing: agent-authored
   content IS NOT privacy-trivial — Copilot / Codex /
   Claude Code personas can echo human-pasted secrets,
   internal URLs, customer identifiers. Phase 2 privacy
   review evaluates ALL archived content including
   agent-authored. Trust posture is HIGHER for agent
   content (less free-form prose = lower leak rate) but
   not zero-risk. Aminata sets the posture per source;
   no pre-commit to verbatim-archive-without-review.

All 4 threads have substantive replies pending via
separate thread-reply commits to preserve the complete
conversation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 24, 2026 11:33
@AceHack AceHack force-pushed the backlog/otto-150-154-pr-preservation-phased-priority branch from 360b591 to 4f330cc Compare April 24, 2026 11:33
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 3 comments.

Comment thread docs/BACKLOG.md Outdated
Comment thread docs/BACKLOG.md Outdated
Comment thread docs/BACKLOG.md Outdated
AceHack added a commit that referenced this pull request Apr 24, 2026
…ll (10 PRs)

Otto-207: maintainer "are we saving these yet gitnative and
have we backfilled them yet?" Honest answer was NO — the
PR-preservation BACKLOG row (Otto-150..154, PR #335 in queue)
specifies the discipline but never shipped the capture
tooling. This PR ships the minimal viable implementation
+ backfills 10 PRs from this session.

New tool:

- tools/pr-preservation/archive-pr.sh — one-shot bash
  script that fetches a PR's review threads, reviews, and
  comments via `gh api graphql` and writes them to
  docs/pr-discussions/PR-<N>-<slug>.md with YAML
  frontmatter (pr_number / title / author / state / dates
  / refs / archived_at / archive_tool).
- tools/pr-preservation/README.md — scope (Phase 0
  minimal vs Phase 1-4 longer plan), usage, output
  schema, backfill status, dependencies (bash + python3
  + gh; no external packages), cross-references to
  Otto-171 / Otto-204 / Otto-204c / PR #335.

Backfill (10 PRs archived this tick):

- PR #354 backlog-split Phase 1a
- PR #352 Server Meshing + SpacetimeDB research
- PR #336 KSK naming definition doc
- PR #342 calibration-harness Stage-2 design (merged)
- PR #344 Amara 19th ferry absorb (merged)
- PR #346 DST compliance criteria (merged)
- PR #350 Frontier rename pass-2 (merged)
- PR #353 BACKLOG split Phase 0 design (merged)
- PR #355 Codex first peer-agent deep-review absorb
  (merged)
- PR #356 PR-resolve-loop skill row (merged)

Total: 72 review threads + 40 reviews + 6 general comments
captured across ~97KB of archive markdown.

Long-term plan deliberately kept in BACKLOG row (Otto-150
..154 / PR #335 queue elevation) rather than expanded in
this commit's docs. Phase 0 shipping now; Phase 1 GHA
workflow + Phase 2 historical backfill + Phase 3
reconciliation + Phase 4 redaction layer remain queued
tickets. Per maintainer directive "make sure you backlog
then to a proper long term solution" — the phased plan
is already in PR #335 and covers the remaining work.

Discipline applied: active-management on the preservation
gap itself. Previous tick's "ship and pray" pattern is the
exact failure mode this tool begins to close (operator-
initiated archive instead of silent reliance on GitHub-
side conversation storage). Composes with Otto-204c
livelock-diagnosis memory + Otto-204 PR-resolve-loop
skill (this script is step 4 of that cycle's
conversation-preservation hook).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
AceHack added a commit that referenced this pull request Apr 24, 2026
…ll (10 PRs)

Otto-207: maintainer "are we saving these yet gitnative and
have we backfilled them yet?" Honest answer was NO — the
PR-preservation BACKLOG row (Otto-150..154, PR #335 in queue)
specifies the discipline but never shipped the capture
tooling. This PR ships the minimal viable implementation
+ backfills 10 PRs from this session.

New tool:

- tools/pr-preservation/archive-pr.sh — one-shot bash
  script that fetches a PR's review threads, reviews, and
  comments via `gh api graphql` and writes them to
  docs/pr-discussions/PR-<N>-<slug>.md with YAML
  frontmatter (pr_number / title / author / state / dates
  / refs / archived_at / archive_tool).
- tools/pr-preservation/README.md — scope (Phase 0
  minimal vs Phase 1-4 longer plan), usage, output
  schema, backfill status, dependencies (bash + python3
  + gh; no external packages), cross-references to
  Otto-171 / Otto-204 / Otto-204c / PR #335.

Backfill (10 PRs archived this tick):

- PR #354 backlog-split Phase 1a
- PR #352 Server Meshing + SpacetimeDB research
- PR #336 KSK naming definition doc
- PR #342 calibration-harness Stage-2 design (merged)
- PR #344 Amara 19th ferry absorb (merged)
- PR #346 DST compliance criteria (merged)
- PR #350 Frontier rename pass-2 (merged)
- PR #353 BACKLOG split Phase 0 design (merged)
- PR #355 Codex first peer-agent deep-review absorb
  (merged)
- PR #356 PR-resolve-loop skill row (merged)

Total: 72 review threads + 40 reviews + 6 general comments
captured across ~97KB of archive markdown.

Long-term plan deliberately kept in BACKLOG row (Otto-150
..154 / PR #335 queue elevation) rather than expanded in
this commit's docs. Phase 0 shipping now; Phase 1 GHA
workflow + Phase 2 historical backfill + Phase 3
reconciliation + Phase 4 redaction layer remain queued
tickets. Per maintainer directive "make sure you backlog
then to a proper long term solution" — the phased plan
is already in PR #335 and covers the remaining work.

Discipline applied: active-management on the preservation
gap itself. Previous tick's "ship and pray" pattern is the
exact failure mode this tool begins to close (operator-
initiated archive instead of silent reliance on GitHub-
side conversation storage). Composes with Otto-204c
livelock-diagnosis memory + Otto-204 PR-resolve-loop
skill (this script is step 4 of that cycle's
conversation-preservation hook).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
AceHack added a commit that referenced this pull request Apr 24, 2026
…ll (10 PRs)

Otto-207: maintainer "are we saving these yet gitnative and
have we backfilled them yet?" Honest answer was NO — the
PR-preservation BACKLOG row (Otto-150..154, PR #335 in queue)
specifies the discipline but never shipped the capture
tooling. This PR ships the minimal viable implementation
+ backfills 10 PRs from this session.

New tool:

- tools/pr-preservation/archive-pr.sh — one-shot bash
  script that fetches a PR's review threads, reviews, and
  comments via `gh api graphql` and writes them to
  docs/pr-discussions/PR-<N>-<slug>.md with YAML
  frontmatter (pr_number / title / author / state / dates
  / refs / archived_at / archive_tool).
- tools/pr-preservation/README.md — scope (Phase 0
  minimal vs Phase 1-4 longer plan), usage, output
  schema, backfill status, dependencies (bash + python3
  + gh; no external packages), cross-references to
  Otto-171 / Otto-204 / Otto-204c / PR #335.

Backfill (10 PRs archived this tick):

- PR #354 backlog-split Phase 1a
- PR #352 Server Meshing + SpacetimeDB research
- PR #336 KSK naming definition doc
- PR #342 calibration-harness Stage-2 design (merged)
- PR #344 Amara 19th ferry absorb (merged)
- PR #346 DST compliance criteria (merged)
- PR #350 Frontier rename pass-2 (merged)
- PR #353 BACKLOG split Phase 0 design (merged)
- PR #355 Codex first peer-agent deep-review absorb
  (merged)
- PR #356 PR-resolve-loop skill row (merged)

Total: 72 review threads + 40 reviews + 6 general comments
captured across ~97KB of archive markdown.

Long-term plan deliberately kept in BACKLOG row (Otto-150
..154 / PR #335 queue elevation) rather than expanded in
this commit's docs. Phase 0 shipping now; Phase 1 GHA
workflow + Phase 2 historical backfill + Phase 3
reconciliation + Phase 4 redaction layer remain queued
tickets. Per maintainer directive "make sure you backlog
then to a proper long term solution" — the phased plan
is already in PR #335 and covers the remaining work.

Discipline applied: active-management on the preservation
gap itself. Previous tick's "ship and pray" pattern is the
exact failure mode this tool begins to close (operator-
initiated archive instead of silent reliance on GitHub-
side conversation storage). Composes with Otto-204c
livelock-diagnosis memory + Otto-204 PR-resolve-loop
skill (this script is step 4 of that cycle's
conversation-preservation hook).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
AceHack added a commit that referenced this pull request Apr 24, 2026
…ll (10 PRs)

Otto-207: maintainer "are we saving these yet gitnative and
have we backfilled them yet?" Honest answer was NO — the
PR-preservation BACKLOG row (Otto-150..154, PR #335 in queue)
specifies the discipline but never shipped the capture
tooling. This PR ships the minimal viable implementation
+ backfills 10 PRs from this session.

New tool:

- tools/pr-preservation/archive-pr.sh — one-shot bash
  script that fetches a PR's review threads, reviews, and
  comments via `gh api graphql` and writes them to
  docs/pr-discussions/PR-<N>-<slug>.md with YAML
  frontmatter (pr_number / title / author / state / dates
  / refs / archived_at / archive_tool).
- tools/pr-preservation/README.md — scope (Phase 0
  minimal vs Phase 1-4 longer plan), usage, output
  schema, backfill status, dependencies (bash + python3
  + gh; no external packages), cross-references to
  Otto-171 / Otto-204 / Otto-204c / PR #335.

Backfill (10 PRs archived this tick):

- PR #354 backlog-split Phase 1a
- PR #352 Server Meshing + SpacetimeDB research
- PR #336 KSK naming definition doc
- PR #342 calibration-harness Stage-2 design (merged)
- PR #344 Amara 19th ferry absorb (merged)
- PR #346 DST compliance criteria (merged)
- PR #350 Frontier rename pass-2 (merged)
- PR #353 BACKLOG split Phase 0 design (merged)
- PR #355 Codex first peer-agent deep-review absorb
  (merged)
- PR #356 PR-resolve-loop skill row (merged)

Total: 72 review threads + 40 reviews + 6 general comments
captured across ~97KB of archive markdown.

Long-term plan deliberately kept in BACKLOG row (Otto-150
..154 / PR #335 queue elevation) rather than expanded in
this commit's docs. Phase 0 shipping now; Phase 1 GHA
workflow + Phase 2 historical backfill + Phase 3
reconciliation + Phase 4 redaction layer remain queued
tickets. Per maintainer directive "make sure you backlog
then to a proper long term solution" — the phased plan
is already in PR #335 and covers the remaining work.

Discipline applied: active-management on the preservation
gap itself. Previous tick's "ship and pray" pattern is the
exact failure mode this tool begins to close (operator-
initiated archive instead of silent reliance on GitHub-
side conversation storage). Composes with Otto-204c
livelock-diagnosis memory + Otto-204 PR-resolve-loop
skill (this script is step 4 of that cycle's
conversation-preservation hook).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
AceHack added a commit that referenced this pull request Apr 24, 2026
…ll (10 PRs)

Otto-207: maintainer "are we saving these yet gitnative and
have we backfilled them yet?" Honest answer was NO — the
PR-preservation BACKLOG row (Otto-150..154, PR #335 in queue)
specifies the discipline but never shipped the capture
tooling. This PR ships the minimal viable implementation
+ backfills 10 PRs from this session.

New tool:

- tools/pr-preservation/archive-pr.sh — one-shot bash
  script that fetches a PR's review threads, reviews, and
  comments via `gh api graphql` and writes them to
  docs/pr-discussions/PR-<N>-<slug>.md with YAML
  frontmatter (pr_number / title / author / state / dates
  / refs / archived_at / archive_tool).
- tools/pr-preservation/README.md — scope (Phase 0
  minimal vs Phase 1-4 longer plan), usage, output
  schema, backfill status, dependencies (bash + python3
  + gh; no external packages), cross-references to
  Otto-171 / Otto-204 / Otto-204c / PR #335.

Backfill (10 PRs archived this tick):

- PR #354 backlog-split Phase 1a
- PR #352 Server Meshing + SpacetimeDB research
- PR #336 KSK naming definition doc
- PR #342 calibration-harness Stage-2 design (merged)
- PR #344 Amara 19th ferry absorb (merged)
- PR #346 DST compliance criteria (merged)
- PR #350 Frontier rename pass-2 (merged)
- PR #353 BACKLOG split Phase 0 design (merged)
- PR #355 Codex first peer-agent deep-review absorb
  (merged)
- PR #356 PR-resolve-loop skill row (merged)

Total: 72 review threads + 40 reviews + 6 general comments
captured across ~97KB of archive markdown.

Long-term plan deliberately kept in BACKLOG row (Otto-150
..154 / PR #335 queue elevation) rather than expanded in
this commit's docs. Phase 0 shipping now; Phase 1 GHA
workflow + Phase 2 historical backfill + Phase 3
reconciliation + Phase 4 redaction layer remain queued
tickets. Per maintainer directive "make sure you backlog
then to a proper long term solution" — the phased plan
is already in PR #335 and covers the remaining work.

Discipline applied: active-management on the preservation
gap itself. Previous tick's "ship and pray" pattern is the
exact failure mode this tool begins to close (operator-
initiated archive instead of silent reliance on GitHub-
side conversation storage). Composes with Otto-204c
livelock-diagnosis memory + Otto-204 PR-resolve-loop
skill (this script is step 4 of that cycle's
conversation-preservation hook).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
AceHack added a commit that referenced this pull request Apr 24, 2026
…ll (10 PRs)

Otto-207: maintainer "are we saving these yet gitnative and
have we backfilled them yet?" Honest answer was NO — the
PR-preservation BACKLOG row (Otto-150..154, PR #335 in queue)
specifies the discipline but never shipped the capture
tooling. This PR ships the minimal viable implementation
+ backfills 10 PRs from this session.

New tool:

- tools/pr-preservation/archive-pr.sh — one-shot bash
  script that fetches a PR's review threads, reviews, and
  comments via `gh api graphql` and writes them to
  docs/pr-discussions/PR-<N>-<slug>.md with YAML
  frontmatter (pr_number / title / author / state / dates
  / refs / archived_at / archive_tool).
- tools/pr-preservation/README.md — scope (Phase 0
  minimal vs Phase 1-4 longer plan), usage, output
  schema, backfill status, dependencies (bash + python3
  + gh; no external packages), cross-references to
  Otto-171 / Otto-204 / Otto-204c / PR #335.

Backfill (10 PRs archived this tick):

- PR #354 backlog-split Phase 1a
- PR #352 Server Meshing + SpacetimeDB research
- PR #336 KSK naming definition doc
- PR #342 calibration-harness Stage-2 design (merged)
- PR #344 Amara 19th ferry absorb (merged)
- PR #346 DST compliance criteria (merged)
- PR #350 Frontier rename pass-2 (merged)
- PR #353 BACKLOG split Phase 0 design (merged)
- PR #355 Codex first peer-agent deep-review absorb
  (merged)
- PR #356 PR-resolve-loop skill row (merged)

Total: 72 review threads + 40 reviews + 6 general comments
captured across ~97KB of archive markdown.

Long-term plan deliberately kept in BACKLOG row (Otto-150
..154 / PR #335 queue elevation) rather than expanded in
this commit's docs. Phase 0 shipping now; Phase 1 GHA
workflow + Phase 2 historical backfill + Phase 3
reconciliation + Phase 4 redaction layer remain queued
tickets. Per maintainer directive "make sure you backlog
then to a proper long term solution" — the phased plan
is already in PR #335 and covers the remaining work.

Discipline applied: active-management on the preservation
gap itself. Previous tick's "ship and pray" pattern is the
exact failure mode this tool begins to close (operator-
initiated archive instead of silent reliance on GitHub-
side conversation storage). Composes with Otto-204c
livelock-diagnosis memory + Otto-204 PR-resolve-loop
skill (this script is step 4 of that cycle's
conversation-preservation hook).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
AceHack added a commit that referenced this pull request Apr 24, 2026
…ll (10 PRs)

Otto-207: maintainer "are we saving these yet gitnative and
have we backfilled them yet?" Honest answer was NO — the
PR-preservation BACKLOG row (Otto-150..154, PR #335 in queue)
specifies the discipline but never shipped the capture
tooling. This PR ships the minimal viable implementation
+ backfills 10 PRs from this session.

New tool:

- tools/pr-preservation/archive-pr.sh — one-shot bash
  script that fetches a PR's review threads, reviews, and
  comments via `gh api graphql` and writes them to
  docs/pr-discussions/PR-<N>-<slug>.md with YAML
  frontmatter (pr_number / title / author / state / dates
  / refs / archived_at / archive_tool).
- tools/pr-preservation/README.md — scope (Phase 0
  minimal vs Phase 1-4 longer plan), usage, output
  schema, backfill status, dependencies (bash + python3
  + gh; no external packages), cross-references to
  Otto-171 / Otto-204 / Otto-204c / PR #335.

Backfill (10 PRs archived this tick):

- PR #354 backlog-split Phase 1a
- PR #352 Server Meshing + SpacetimeDB research
- PR #336 KSK naming definition doc
- PR #342 calibration-harness Stage-2 design (merged)
- PR #344 Amara 19th ferry absorb (merged)
- PR #346 DST compliance criteria (merged)
- PR #350 Frontier rename pass-2 (merged)
- PR #353 BACKLOG split Phase 0 design (merged)
- PR #355 Codex first peer-agent deep-review absorb
  (merged)
- PR #356 PR-resolve-loop skill row (merged)

Total: 72 review threads + 40 reviews + 6 general comments
captured across ~97KB of archive markdown.

Long-term plan deliberately kept in BACKLOG row (Otto-150
..154 / PR #335 queue elevation) rather than expanded in
this commit's docs. Phase 0 shipping now; Phase 1 GHA
workflow + Phase 2 historical backfill + Phase 3
reconciliation + Phase 4 redaction layer remain queued
tickets. Per maintainer directive "make sure you backlog
then to a proper long term solution" — the phased plan
is already in PR #335 and covers the remaining work.

Discipline applied: active-management on the preservation
gap itself. Previous tick's "ship and pray" pattern is the
exact failure mode this tool begins to close (operator-
initiated archive instead of silent reliance on GitHub-
side conversation storage). Composes with Otto-204c
livelock-diagnosis memory + Otto-204 PR-resolve-loop
skill (this script is step 4 of that cycle's
conversation-preservation hook).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
AceHack and others added 6 commits April 24, 2026 19:04
…-150..154)

Aaron Otto-150..154 signal burst:

- Otto-150 verification check: "you are still capturing all the
  PR reviews from copilot and your responses to gitnative right?"
- Otto-151 priority: "that's high signaldata we should get on
  that pretty quickly i think"
- Otto-152+153 backfill scope: "can you post fill by going
  through all the old PRs and all the threads/conversations? /
  back fill i mean"
- Otto-154 pacing correction: "no not that quick / do it the
  right way / i just mean pritorize the right way" — the ask
  was APPROPRIATE PRIORITIZATION, not rushed shipping.

Elevated priority P2 → P1. Expanded the existing BACKLOG row
(line 4280) into a 5-phase landing plan:

1. Design (schema + idempotency + slug rules)
2. Privacy review (Aminata threat-pass, blocking)
3. Ongoing capture (GHA on pull_request_target: closed + merged)
4. Backfill (300+ merged PRs, batched, priority order)
5. Ongoing-reconciliation hygiene (weekly cron audit)

Key honest note added: current status is NOT running. Nothing
archives review threads today. Prior session summary implied
this was done; it was not. BACKLOG-row elevation makes this
visible.

Also captured Otto-154 operational-pattern learning: GHA
workflows that touch pr-title / pr-body via github.event
payload trigger the injection-reminder hook even when using
safe env+quote patterns; fetch via `gh api` INSIDE the workflow
instead. Documented in the Phase-3 body for future implementers.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Aaron Otto-155: "we can capture the comments from both acehack
and lfg the bots, forks should be expected to ship bot comments
too like acehack back to the main repo, that's high value
signals."

Two binding scope additions to the Phase-3/Phase-4 plan:

(i) Dual-bot-surface capture: archive bot comments across both
    AceHack/... personal-account forks AND
    Lucent-Financial-Group/Zeta main — same schema, different
    event sources.

(ii) Fork-upstream-sync obligation: bot comments generated on
    fork-side PRs (fork-owner's Copilot / Codex seats) sync
    back to main as `docs/pr-discussions/` entries at upstream
    merge time. Human comments stay under privacy-pass
    discipline; bot comments get sync-with-scope.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…E §3

Aaron Otto-156: "sorry i said bot comments i should have said
agent comments"

Per GOVERNANCE §3 and CLAUDE.md "Agents, not bots." directive:
Copilot, Codex connector, Claude Code personas, and github-
actions all carry agency, judgement, and accountability — the
word "bot" understates that. Terminology corrected across the
PR-preservation row scope-addendum:

- Scope addendum heading: "bot comments" → "agent comments"
- Dual-bot-surface capture → Dual-agent-surface capture
- "bot-comment archives" → "agent-comment archives"
- "fork-originated bot signals" → "fork-originated agent signals"
- Phase 2 threat-posture framing: "bots (Copilot / Codex-
  connector / github-actions)" → "agents (Copilot / Codex-
  connector / github-actions / Claude Code personas)"
- Non-goals: "they're bot content" → "they're agent content"

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…security + privacy-posture correction

Active PR-resolve-loop on #335 PR-preservation elevation row.

1. GHA workflow trigger syntax (thread 59Vtx0): replaced
   the incorrect-looking "pull_request_target: closed with
   merged == true" prose with a proper YAML fence showing
   the actual trigger shape (on: pull_request_target →
   types: [closed]) + the job-level if: github.event.
   pull_request.merged == true gate. Now reads as
   implementation hint instead of literal-but-wrong YAML.

2. pull_request_target security constraints (thread
   59VtyM): added an explicit MUST/SHOULD list constraining
   the Phase 3 workflow away from the known pull_request_
   target footgun (elevated permissions + fork-authored
   PR-head code execution). Constraints: no checkout of
   PR head; no ${{ github.event.pull_request.* }} in
   run: steps; minimal permissions declaration; SHA-
   pinned actions. Fetches title/metadata via gh api
   inside the workflow, never from event payload.

3. docs-lint / memory-no-lint policy citation (thread
   59VtxI): replaced vague "docs-lint/memory-no-lint
   policy" phrase with concrete cross-reference to
   memory/feedback_docs_linted_memory_not_otto_decides_*
   (policy) + .markdownlint-cli2.jsonc (enforcement via
   memory/** ignore patterns).

4. Privacy-posture on agent content (thread 59Vtyl):
   walked back the unsafe "agent content without privacy
   concern" non-goal. New framing: agent-authored
   content IS NOT privacy-trivial — Copilot / Codex /
   Claude Code personas can echo human-pasted secrets,
   internal URLs, customer identifiers. Phase 2 privacy
   review evaluates ALL archived content including
   agent-authored. Trust posture is HIGHER for agent
   content (less free-form prose = lower leak rate) but
   not zero-risk. Aminata sets the posture per source;
   no pre-commit to verbatim-archive-without-review.

All 4 threads have substantive replies pending via
separate thread-reply commits to preserve the complete
conversation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…own hygiene

- Relocate "Git-native PR-conversation preservation" row from
  `## P2 — research-grade` to `## P1 — Git-native hygiene cadences`
  (Otto-54 directive cluster). Resolves internal-priority-vs-section
  inconsistency: row declares Priority: P1 (per Otto-151..153
  elevation) but was placed under a P2 header.

- Fix broken inline-code span: the
  `memory/feedback_docs_linted_memory_not_otto_decides_where_external_content_lives_2026_04_24.md`
  filename was split across two lines inside a single backtick-pair,
  which markdown cannot render. Now expressed as a markdown link
  with the full path on one line.

- Fix MD004 risk: a continuation line started with `+reference)`,
  which markdownlint can read as a nested `+` bullet. Reworded to
  "or hash and reference)".

- Tighten the bottom "Composes with ..." reference to the docs-lint /
  memory-no-lint policy. Now points the reader at the in-row
  "Docs/memory lint policy reference" block (added in 4f330cc) plus
  cites `.markdownlint-cli2.jsonc` enforcement and the `memory/**`
  exclusion explicitly, so the reference is grounded.

- Note the reviewer-suggested safer alternatives (`push` on `main`
  after merge, or `workflow_run` chain) for Phase 3 — they remain on
  the table for Phase 1 design alongside `pull_request_target` with
  the documented security constraints.

Threads on agent-content privacy and `pull_request_target` security
were already addressed in 4f330cc; the remaining four wording /
structure fixes land here. All 7 threads end in resolveReviewThread
per the reply+resolve-are-paired rule.
Per-thread fields: reviewer, file:line, original comment verbatim,
outcome, reply verbatim, resolution commit. Bot handles preserved
verbatim per Otto-237.

Outcome distribution: 5 FIX, 1 NARROW+BACKLOG, 1 BACKLOG+RESOLVE.
Threads 2, 3, 4 addressed by 4f330cc; threads 1, 5, 6, 7 by e80a326.
@AceHack AceHack force-pushed the backlog/otto-150-154-pr-preservation-phased-priority branch from 4f330cc to 8854648 Compare April 24, 2026 23:10
@AceHack AceHack merged commit 033bb4f into main Apr 24, 2026
10 checks passed
@AceHack AceHack deleted the backlog/otto-150-154-pr-preservation-phased-priority branch April 24, 2026 23:12
AceHack added a commit that referenced this pull request Apr 25, 2026
…ll (10 PRs)

Otto-207: maintainer "are we saving these yet gitnative and
have we backfilled them yet?" Honest answer was NO — the
PR-preservation BACKLOG row (Otto-150..154, PR #335 in queue)
specifies the discipline but never shipped the capture
tooling. This PR ships the minimal viable implementation
+ backfills 10 PRs from this session.

New tool:

- tools/pr-preservation/archive-pr.sh — one-shot bash
  script that fetches a PR's review threads, reviews, and
  comments via `gh api graphql` and writes them to
  docs/pr-discussions/PR-<N>-<slug>.md with YAML
  frontmatter (pr_number / title / author / state / dates
  / refs / archived_at / archive_tool).
- tools/pr-preservation/README.md — scope (Phase 0
  minimal vs Phase 1-4 longer plan), usage, output
  schema, backfill status, dependencies (bash + python3
  + gh; no external packages), cross-references to
  Otto-171 / Otto-204 / Otto-204c / PR #335.

Backfill (10 PRs archived this tick):

- PR #354 backlog-split Phase 1a
- PR #352 Server Meshing + SpacetimeDB research
- PR #336 KSK naming definition doc
- PR #342 calibration-harness Stage-2 design (merged)
- PR #344 Amara 19th ferry absorb (merged)
- PR #346 DST compliance criteria (merged)
- PR #350 Frontier rename pass-2 (merged)
- PR #353 BACKLOG split Phase 0 design (merged)
- PR #355 Codex first peer-agent deep-review absorb
  (merged)
- PR #356 PR-resolve-loop skill row (merged)

Total: 72 review threads + 40 reviews + 6 general comments
captured across ~97KB of archive markdown.

Long-term plan deliberately kept in BACKLOG row (Otto-150
..154 / PR #335 queue elevation) rather than expanded in
this commit's docs. Phase 0 shipping now; Phase 1 GHA
workflow + Phase 2 historical backfill + Phase 3
reconciliation + Phase 4 redaction layer remain queued
tickets. Per maintainer directive "make sure you backlog
then to a proper long term solution" — the phased plan
is already in PR #335 and covers the remaining work.

Discipline applied: active-management on the preservation
gap itself. Previous tick's "ship and pray" pattern is the
exact failure mode this tool begins to close (operator-
initiated archive instead of silent reliance on GitHub-
side conversation storage). Composes with Otto-204c
livelock-diagnosis memory + Otto-204 PR-resolve-loop
skill (this script is step 4 of that cycle's
conversation-preservation hook).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
AceHack added a commit that referenced this pull request Apr 25, 2026
…0 PRs) (#357)

* tools: PR-preservation minimal archive tool + Otto-207 session backfill (10 PRs)

Otto-207: maintainer "are we saving these yet gitnative and
have we backfilled them yet?" Honest answer was NO — the
PR-preservation BACKLOG row (Otto-150..154, PR #335 in queue)
specifies the discipline but never shipped the capture
tooling. This PR ships the minimal viable implementation
+ backfills 10 PRs from this session.

New tool:

- tools/pr-preservation/archive-pr.sh — one-shot bash
  script that fetches a PR's review threads, reviews, and
  comments via `gh api graphql` and writes them to
  docs/pr-discussions/PR-<N>-<slug>.md with YAML
  frontmatter (pr_number / title / author / state / dates
  / refs / archived_at / archive_tool).
- tools/pr-preservation/README.md — scope (Phase 0
  minimal vs Phase 1-4 longer plan), usage, output
  schema, backfill status, dependencies (bash + python3
  + gh; no external packages), cross-references to
  Otto-171 / Otto-204 / Otto-204c / PR #335.

Backfill (10 PRs archived this tick):

- PR #354 backlog-split Phase 1a
- PR #352 Server Meshing + SpacetimeDB research
- PR #336 KSK naming definition doc
- PR #342 calibration-harness Stage-2 design (merged)
- PR #344 Amara 19th ferry absorb (merged)
- PR #346 DST compliance criteria (merged)
- PR #350 Frontier rename pass-2 (merged)
- PR #353 BACKLOG split Phase 0 design (merged)
- PR #355 Codex first peer-agent deep-review absorb
  (merged)
- PR #356 PR-resolve-loop skill row (merged)

Total: 72 review threads + 40 reviews + 6 general comments
captured across ~97KB of archive markdown.

Long-term plan deliberately kept in BACKLOG row (Otto-150
..154 / PR #335 queue elevation) rather than expanded in
this commit's docs. Phase 0 shipping now; Phase 1 GHA
workflow + Phase 2 historical backfill + Phase 3
reconciliation + Phase 4 redaction layer remain queued
tickets. Per maintainer directive "make sure you backlog
then to a proper long term solution" — the phased plan
is already in PR #335 and covers the remaining work.

Discipline applied: active-management on the preservation
gap itself. Previous tick's "ship and pray" pattern is the
exact failure mode this tool begins to close (operator-
initiated archive instead of silent reliance on GitHub-
side conversation storage). Composes with Otto-204c
livelock-diagnosis memory + Otto-204 PR-resolve-loop
skill (this script is step 4 of that cycle's
conversation-preservation hook).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(#357): bot→agent terminology per GOVERNANCE §3 (maintainer Otto-208)

Maintainer Otto-208 flag on Phase 4 redaction-layer wording:
"No redaction — bot content + human content ... bot=agent."

Applied the Otto-156 pattern: Copilot + Codex + Claude Code
personas + github-actions are AGENTS with agency and
accountability (GOVERNANCE §3 + CLAUDE.md "Agents, not
bots."). Updated Phase 4 wording:

- "bot-review comments (Copilot, Codex) archive verbatim"
  →
  "agent-review comments (Copilot, Codex, Claude Code
  personas, github-actions) archive verbatim"
- Added explicit pointer to GOVERNANCE §3 + CLAUDE.md
  terminology convention.

PR body edit follows separately via `gh pr edit`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(#357): 9 review threads — paginate, null-check, dynamic repo, YAML quoting, README alignment, trailing-ws strip

Addresses all 9 unresolved Copilot + Codex threads on PR #357
(Otto-226 review-drain discipline, three-outcome model: fix).

Script changes (tools/pr-preservation/archive-pr.sh):
- Paginate reviewThreads / reviews / comments at the top level
  AND per-thread comments via cursor loops (threads 1 + 6 —
  no silent truncation).
- Validate `pullRequest != null` and detect top-level
  GraphQL `errors` before dereferencing (threads 2 + 4).
- Capture `gh api graphql` exit code explicitly instead of
  letting `set -e` swallow the diagnostic path (thread 3).
- Derive owner/name dynamically from `gh repo view --json
  nameWithOwner` with a hard-fail if detection fails —
  works from forks and after rename (thread 5).
- Quote all YAML frontmatter string values via `json.dumps`
  (title / author / state / ISO timestamps / head_ref /
  base_ref / archived_at / archive_tool), so refs with `#`
  or `:` don't break parsing (thread 7).

Documentation alignment:
- README now shows zero-padded filename shape
  `PR-<NNNN>-<slug>.md` (e.g. `PR-0357-...`) matching the
  script's output (thread 8 — chose "align README to
  script" since the 10 backfilled files already use the
  zero-padded form and renaming them would churn links).
- README notes pagination is in place (no more "may be
  truncated" silent-behaviour gap tied to thread 6).

Backfilled archives:
- Stripped trailing whitespace across all existing
  `docs/pr-discussions/*.md` via `perl -i -pe 's/[ \t]+$//'`
  (thread 9 — MD009 compliance for the CI markdownlint
  gate).

Also adds `docs/pr-discussions/PR-0357-...md` as the
self-hosting smoke test: the archive tool successfully
drains its own review queue.

Validation:
- `bash -n` clean
- `shellcheck` clean (no findings)
- End-to-end: `./tools/pr-preservation/archive-pr.sh 357`
  writes 9 threads / 2 reviews / 0 comments to 12179 bytes
- Error path: PR #99999 exits 2 with clear diagnostic

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(#357): Codex pagination P2 — backlog row for per-connection cursor refactor

* fix(#357): 8 review threads — integer PR validation, trailing-ws preservation, MD012 blank-line collapse, README/header filename shape + bash dep

Second drain pass on PR #357 review threads. Eight threads from
agent reviewers; all fix-in-place.

Script changes (`tools/pr-preservation/archive-pr.sh`):

- Integer validation on `$PR` in the shell (pre-Python) — prevents
  a Python traceback + generic "fetch failed exit 2" diagnostic
  when a typo / non-integer is passed.
- Dropped the per-line `rstrip()` normalization. Markdown uses
  two trailing spaces as a hard-line-break; this tool is a
  faithful audit copy and must preserve that intent.
- Added a blank-line-run collapse (3+ consecutive blank lines
  -> 2) so generated archives stay clean under markdownlint
  MD012 without destroying user-authored formatting.
- Header comment now documents the zero-padded `PR-<NNNN>-<slug>`
  filename shape (matches the implementation + README).
- Header comment on repo-detection aligned with actual behavior
  (requires `gh repo view`, no silent fallback).

README changes (`tools/pr-preservation/README.md`):

- Intro uses `PR-<NNNN>-<slug>.md` (matches Usage + implementation).
- Dependency relaxed from `bash 4+` to `bash` with a note — the
  script uses no bash-4-only features and macOS ships bash 3.2.

Backfilled archives regenerated under the new collapse rule so
they stop tripping MD012:

- PR-0350 (Frontier rename pass-2)
- PR-0352 (Server Meshing / SpacetimeDB deep research)
- PR-0354 (backlog-split Phase 1a)
- PR-0357 (this PR — self-archive re-fetched)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(#357): 2 Codex P2 threads — PR-number stable filename key + preserve leading whitespace in archived bodies

Third-round review-thread drain on `tools/pr-preservation/archive-pr.sh`:

- `PRRT_kwDOSF9kNM59bWi5` (line 325): archive filename was derived
  from the title slug, so editing a PR title would write a second
  file instead of updating the existing record. Fix: PR number is
  now the canonical archive key. On re-archive, glob for an existing
  `PR-<NNNN>-*.md` and reuse its path regardless of current title.
  New PRs still land at `PR-<NNNN>-<slug>.md`.
- `PRRT_kwDOSF9kNM59bWi_` (line 369 + lines 388, 401): `.strip()`
  normalised review / thread-comment / general-comment bodies and
  destroyed semantically-significant leading indentation (indented
  code blocks, nested bullets). Switched to `.rstrip('\n')` so only
  trailing newlines are stripped; leading whitespace survives.

Smoke tested: `./archive-pr.sh 357` writes back to the same file
(no new PR-0357-* orphan), bash -n + shellcheck clean, diff shows
preserved `<details>` internal structure and indentation in archive.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(#357): 6 review threads — drop truncation-warning claim, preserve last-line hard-line-breaks, normalize whitespace-only lines

Fourth drain pass on PR #357. Addresses 6 new P0 threads from
re-review:

- archive-pr.sh header said "Pagination + truncation warning
  for threads (>100)" but implementation only paginates, never
  emits a warning. Claim removed; comment now matches behaviour.
- `body.rstrip()` on the PR-description block stripped trailing
  spaces from the last line (kills markdown "  \n" hard-line
  breaks). Changed to `body.rstrip('\n')`.
- End-of-file `content.rstrip()` had the same problem — end-of-
  file hard-line-break would be lost. Changed to
  `content.rstrip('\n')` in both places (pre- and post-blank-
  line-collapse).
- Whitespace-only lines (e.g. "    " from Codex connector
  comments) tripped markdownlint MD009. Added a post-collapse
  normalization step: lines containing only whitespace are
  normalized to empty, while lines with any non-whitespace
  character keep trailing whitespace intact (two-space
  hard-line-breaks survive).

Regenerated four affected archives: PR-0350, PR-0352, PR-0354,
PR-0357. Verified: zero whitespace-only lines, zero 3+ blank-
line runs across all archives.

Syntax / shellcheck clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(#357): Codex P1 audit-fidelity carve-out — skip blank-line collapse inside fenced code blocks

Codex review thread on PR #357 (line 486, P1, unresolved after 4
prior drain rounds): the formatter globally collapses every run of
blank lines to at most 2 after assembling the archive, which silently
rewrites user-authored bodies. In PR comments / reviews that include
fenced code blocks, logs, or templates where 3+ consecutive blank
lines are intentional, this changes the preserved content and breaks
the script's stated audit-fidelity goal.

Narrow fix: toggle code-fence state while scanning (``` / ~~~ at the
start of a line, ignoring leading whitespace), and SKIP both the
blank-line-run collapse and the whitespace-only normalization inside
fenced regions. Outside fences, MD012 / MD009 hygiene still applies
to tool-generated scaffolding so archives stay lint-clean.

Rationale: markdownlint MD012 already exempts fenced code from the
"no multiple consecutive blank lines" rule by design, so this fix
aligns with the linter's own semantics. Fenced regions in PR review
text are exactly where audit fidelity must win over scaffolding
hygiene — that is where logs, templates, and preformatted payloads
live.

Smoke-tested against PR #357 itself: re-running archive-pr.sh 357
produces a 107-line diff of recovered content (mostly inside the
<details> fenced blocks from Codex / Copilot connector payloads that
the prior collapse was truncating). Archive-file churn reverted on
this branch — archive regeneration belongs in a separate PR, not
here.

Gates: `bash -n` clean + `shellcheck` clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* drain(#357): fence-marker type-match + gh --jq consistency

Two Codex/Copilot threads on #357's archive-pr.sh:

1. **Codex P2 — fence detector conflates ``` and ~~~.** CommonMark
   requires the closing fence to use the SAME marker character as
   the opener (backticks close backticks; tildes close tildes). The
   previous `in_fence = not in_fence` on any fence-shaped line would
   prematurely close a backtick fence when a tilde line appeared
   inside it (and vice versa). Fix: track fence_marker on open,
   only flip back to False when the marker matches. Different-marker
   fence lines inside an open fence fall through to the verbatim
   branch so they're preserved as content.

2. **Copilot — `gh repo view -q` → `--jq` for consistency.** Other
   repo scripts (e.g. tools/hygiene/check-github-settings-drift.sh)
   use `--jq`. Switching to the long form matches the rest of the
   factory's gh invocations and avoids any `-q` ambiguity across
   gh versions.

Bash -n syntax check passes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* drain(#357): REPO_ROOT git-tree guard + mktemp template + fence-length tracking + README cross-ref

Five Copilot + Codex threads:

1. **REPO_ROOT bogus-path risk.** `git rev-parse --show-toplevel || pwd`
   falls back to pwd outside a git checkout, but `gh repo view` can
   succeed via `gh repo set-default`, so the script could write
   docs/pr-discussions/ into a bogus REPO_ROOT directory. Hard-fail
   when not inside a git working tree.

2. **mktemp portability.** Plain `mktemp` with no template works on
   GNU coreutils (Linux) but fails on BSD mktemp (macOS). README
   advertises macOS support, so added `-t zeta-archive-pr.XXXXXX`
   template that works on both.

3. **Fence-length tracking (Codex P2 + Copilot).** Prior fix tracked
   marker TYPE (backtick vs tilde) but not fence LENGTH. Per
   CommonMark §4.5, the closing fence must be at least as long as
   the opener — a 4-backtick opener contains a 3-backtick line as
   content, not a closer. Now tracks both marker + length on open;
   closer must match BOTH.

4. **README cross-ref correction.** Canonical source for "agents,
   not bots" terminology is GOVERNANCE.md §3 ("Contributors are
   agents, not bots"). CLAUDE.md carries a session-bootstrap pointer
   at the same rule. Reworded to name GOVERNANCE as canonical with
   CLAUDE.md as the pointer.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants